﻿
namespace AutoWiring.Common
{
    /// <summary>
    /// Revit直线类
    /// </summary>
    public class Line
    {
        /// <summary>
        /// 直线起点
        /// </summary>
        public XYZ StartPoint { get; set; }

        /// <summary>
        /// 直线终点
        /// </summary>
        public XYZ EndPoint { get; set; }

        /// <summary>
        /// 线段长度
        /// </summary>
        public double Length { get { return StartPoint.DistanceTo(EndPoint); } }

        /// <summary>
        /// 线向量
        /// </summary>
        public XYZ Direction { get { return EndPoint.Subtract(StartPoint); } }

        /// <summary>
        /// 线段斜率
        /// </summary>
        public double Slope { get { return (EndPoint.Y - StartPoint.Y) / (EndPoint.X - StartPoint.X); } }

        /// <summary>
        /// 构造函数创建直线
        /// </summary>
        /// <param name="StartPoint"></param>
        /// <param name="EndPoint"></param>
        public Line(XYZ StartPoint, XYZ EndPoint)
        {
            this.StartPoint = StartPoint;
            this.EndPoint = EndPoint;
        }

        /// <summary>
        /// 创建Line
        /// </summary>
        /// <param name="StartPoint"></param>
        /// <param name="EndPoint"></param>
        /// <returns></returns>
        public static Line Create(XYZ StartPoint, XYZ EndPoint)
        {
            return new Line(StartPoint, EndPoint);
        }

        /// <summary>
        /// 获得两条线的交点
        /// </summary>
        /// <param name="Source"></param>
        /// <returns></returns>
        public XYZ FindIntersection(Line Source)
        {

            // 第一根线XY投影参数方程 A11*X+B11*Y+C11=0
            double A11 = this.EndPoint.Y - this.StartPoint.Y;
            double B11 = this.StartPoint.X - this.EndPoint.X;
            double C11 = this.EndPoint.X * this.StartPoint.Y - this.StartPoint.X * this.EndPoint.Y;
            // 第二根线XY投影参数方程 A22*X+B22*Y+C22=0
            double A22 = Source.EndPoint.Y - Source.StartPoint.Y;
            double B22 = Source.StartPoint.X - Source.EndPoint.X;
            double C22 = Source.EndPoint.X * Source.StartPoint.Y - Source.StartPoint.X * Source.EndPoint.Y;

            double delta = A11 * B22 - A22 * B11;
            if (delta == 0) return null;

            double x = (B11 * C22 - B22 * C11) / delta;
            double y = (A22 * C11 - A11 * C22) / delta;

            // 计算Z值
            XYZ sp = new XYZ(x, y, 0).Subtract(new XYZ(this.StartPoint.X, this.StartPoint.Y, 0));
            double angle = sp.AngleTo(this.Direction);

            double tanValue = sp.Length() * Math.Tan(angle);
            XYZ des = new XYZ(x, y, tanValue);
            // 判断点是否在爱另一条线上
            if (!des.Subtract(Source.StartPoint).Normalize().IsParallel(Source.EndPoint.Subtract(des).Normalize()))
            {
                return null;
            }
            else
            {
                return des;
            }


        }

        /// <summary>
        /// 返回点到直线的最小距离
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public double PointToLineDistance(XYZ point)
        {
            XYZ vector1 = this.StartPoint.Subtract(point);
            XYZ vector2 = this.EndPoint.Subtract(this.StartPoint);
            XYZ crossProduct = vector1.CrossProduct(vector2);

            return crossProduct.Length() / vector2.Length();
        }

        /// <summary>
        /// 返回点到直线最小距离点的坐标
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public XYZ PointToLineDistanceXYZ(XYZ point)
        {
            XYZ vector1 = point.Subtract(this.StartPoint);
            XYZ vector2 = this.EndPoint.Subtract(this.StartPoint);
            double angle = vector1.AngleTo(vector2);
            double angle1 = vector1.Length() * Math.Cos(angle);

            return this.StartPoint.Add(vector2.Normalize().Multiply(vector1.Length() * Math.Cos(angle)));
        }
    }
}
